home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / 7Edit 3.1 / Sources / SVAECompare.c < prev    next >
Encoding:
Text File  |  1995-11-20  |  7.2 KB  |  307 lines  |  [TEXT/CWIE]

  1. // SVAECompare.c
  2. //
  3. // 7Edit 3.1d1. Original version by Jon Lansdell and Nigel Humphreys.
  4. // 3.1 updates by Greg Sutton.
  5. // ©Apple Computer Inc 1995, all rights reserved.
  6.  
  7. #include "SVAECompare.h"
  8.  
  9. #include <AEPackObject.h>
  10. #include "SVEditGlobals.h"
  11. #include "SVEditUtils.h"
  12. #include "SVEditAEUtils.h"
  13. #include "SVEditWindow.h"
  14. #include "SVEditFile.h"
  15. #include "SVAppleEvents.h"
  16.  
  17. #include "SVToken.h"
  18. #include "SVAECountElements.h"
  19. #include "SVAEGetData.h"
  20.  
  21. #include <string.h>
  22.  
  23.  
  24. #pragma segment AppleEvent
  25.  
  26.  
  27. OSErr    InstallObjectCallbacks(void)
  28. {
  29.     OSErr    err;
  30.  
  31.     err = AESetObjectCallbacks(NewOSLCompareProc(MyCompareProc),
  32.                                 NewOSLCountProc(MyCountProc),
  33.                                 NULL, NULL, NULL, NULL, NULL);
  34.                                 
  35.     return(err);
  36. }
  37.  
  38.  
  39. pascal OSErr    MyCompareProc(DescType oper, const AEDesc* obj1, const AEDesc* obj2, Boolean* result)
  40. {
  41.     AEDesc        desc1     = {typeNull, NULL};
  42.     AEDesc        desc2     = {typeNull, NULL};
  43.     AEDesc        tempDesc = {typeNull, NULL};
  44.     OSErr        err;
  45.     
  46.     err = ExtractData(obj1, &desc1);
  47.     if (err != noErr) goto done;
  48.     err = ExtractData(obj2, &desc2);
  49.     if (err != noErr) goto done;
  50.  
  51.     // Make sure the 2 data types are the same
  52.     if (desc1.descriptorType != desc2.descriptorType)
  53.     {
  54.         err = AEDuplicateDesc(&desc2, &tempDesc);
  55.         if (err != noErr) goto done;
  56.         err = AEDisposeDesc(&desc2);
  57.         err = AECoerceDesc(&tempDesc, desc1.descriptorType, &desc2);
  58.         if (err != noErr)                        // If we can't coerce one way, try
  59.         {                                        // the opposite way.
  60.             err = AEDuplicateDesc(&tempDesc, &desc2);    // We disposed of desc2
  61.             err = AEDisposeDesc(&tempDesc);
  62.             err = AEDuplicateDesc(&desc1, &tempDesc);
  63.             if (err != noErr) goto done;
  64.             err = AEDisposeDesc(&desc1);
  65.             err = AECoerceDesc(&tempDesc, desc2.descriptorType, &desc1);
  66.             if (err != noErr) goto done;
  67.         }
  68.     }
  69.     
  70.     // Now that we know that the 2 types are the same, go ahead and run the compare
  71.     switch(desc1.descriptorType)
  72.     {
  73.         case typeChar:
  74.             err = MyCompareText(oper, &desc1, &desc2, result);
  75.             break;
  76.         
  77.         case typeShortInteger:
  78.         case typeLongInteger:
  79.             err = MyCompareInteger(oper, &desc1, &desc2, result);
  80.             break;
  81.  
  82.         case typeBoolean:
  83.             err = MyCompareBoolean(oper, &desc1, &desc2, result);
  84.             break;
  85.                 
  86.         default:
  87.             err = errAEWrongDataType;
  88.     }
  89.     
  90. done:
  91.     if (desc1.dataHandle)
  92.         (void) AEDisposeDesc(&desc1);
  93.     if (desc2.dataHandle)
  94.         (void) AEDisposeDesc(&desc2);
  95.     if (tempDesc.dataHandle)
  96.         (void) AEDisposeDesc(&tempDesc);
  97.     
  98.     return(err);
  99. }
  100.  
  101.  
  102. OSErr    ExtractData(const AEDesc *sourceDesc, AEDesc *theData)
  103. {
  104.     AEDesc        intermediateDesc = {typeNull, NULL};
  105.     OSErr        err;
  106.     
  107.     // This routine can receive: An Object specifier, an object token, a property token, or
  108.     // some data (TEXT, Rectangle, etc.). It needs to convert whatever it's handed into data
  109.     // and return that.
  110.     
  111.     // If we don't have any data, complain
  112.     if (sourceDesc->descriptorType == typeNull || sourceDesc->dataHandle == NULL)
  113.         return(errAENoSuchObject);
  114.     
  115.     // If it's an object specifier, resolve into a token
  116.     if (sourceDesc->descriptorType == typeObjectSpecifier)
  117.         err = AEResolve(sourceDesc, kAEIDoMinimum, &intermediateDesc);
  118.     else    // Otherwise, just copy it
  119.         err = AEDuplicateDesc(sourceDesc, &intermediateDesc);
  120.  
  121.     if (err != noErr) goto done;
  122.     
  123.     // Now that we have a token, read from it
  124.     switch (intermediateDesc.descriptorType)
  125.     {
  126.         case typeMyApplProp:
  127.         case typeMyTextProp:
  128.         case typeMyWindowProp:
  129.         case typeMyText:
  130.             err = HandleGetData(&intermediateDesc, theData);
  131.             break;
  132.  
  133.         default:
  134.             // This is probably raw data , so pass it back up the line
  135.             err = AEDuplicateDesc(&intermediateDesc, theData);
  136.     }
  137.  
  138. done:
  139.     if (intermediateDesc.dataHandle)
  140.         (void) AEDisposeDesc(&intermediateDesc);
  141.  
  142.     return(err);
  143. }
  144.  
  145.  
  146. OSErr    MyCompareText(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  147. {
  148.     int        compareResult;
  149.     long    compareSize;
  150.     long    textSize1, textSize2;
  151.     char    *testStr, *compareStr;
  152.     OSErr    err = noErr;
  153.     
  154.     textSize1 = GetHandleSize(desc1->dataHandle);
  155.     HLockHi(desc1->dataHandle);
  156.     textSize2 = GetHandleSize(desc2->dataHandle);
  157.     HLockHi(desc2->dataHandle);
  158.     if (textSize1 <= textSize2)
  159.     {
  160.         switch (oper)
  161.         {
  162.             case kAEBeginsWith:        // Can't begin or end or contain any string
  163.             case kAEEndsWith:        // longer than itself
  164.             case kAEContains:
  165.                 *result = false;
  166.                 return(noErr);
  167.         }
  168.     
  169.         compareSize = textSize1;
  170.     }
  171.     else
  172.         compareSize = textSize2;
  173.     
  174.     switch (oper)
  175.     {
  176.         case kAEEndsWith:            // Offset to end of string
  177.             testStr = (char *)(*desc1->dataHandle + textSize1 - textSize2);    
  178.             break;
  179.         
  180.         case kAEContains:
  181.             testStr = NewPtr(textSize1 + 1);
  182.             BlockMove(*desc1->dataHandle, testStr, textSize1);
  183.             testStr[textSize1] = '\0';
  184.             compareStr = NewPtr(textSize2 + 1);
  185.             BlockMove(*desc2->dataHandle, compareStr, textSize2);
  186.             compareStr[textSize2] = '\0';
  187.             *result = (NULL != strstr(testStr,compareStr));
  188.             DisposePtr(testStr);
  189.             DisposePtr(compareStr);
  190.             return(noErr);
  191.         
  192.         default:
  193.             testStr = (char *)*desc1->dataHandle;
  194.     }
  195.     
  196.     compareResult = strncmp(testStr, (char *)*desc2->dataHandle, compareSize);
  197.     
  198.     HUnlock(desc1->dataHandle);
  199.     HUnlock(desc2->dataHandle);
  200.  
  201.     switch (oper)
  202.     {
  203.         case kAEEquals:
  204.             *result = (textSize1 == textSize2 && compareResult == 0);
  205.             break;
  206.  
  207.         case kAEBeginsWith:
  208.         case kAEEndsWith:
  209.             *result = (compareResult == 0);
  210.             break;
  211.  
  212.         case kAELessThan:
  213.             *result = (compareResult < 0);
  214.             break;
  215.         
  216.         case kAELessThanEquals:
  217.             *result = (compareResult <= 0);
  218.             break;
  219.         
  220.         case kAEGreaterThan:
  221.             *result = (compareResult > 0);
  222.             break;
  223.         
  224.         case kAEGreaterThanEquals:
  225.             *result = (compareResult >= 0);
  226.             break;
  227.         
  228.         default:
  229.             err = errAEBadTestKey;
  230.     }
  231.  
  232.     return(err);
  233. }
  234.  
  235.  
  236. OSErr    MyCompareInteger(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  237. {
  238.     long    num1, num2;
  239.     AEDesc    longDesc = {typeNull, NULL};
  240.     OSErr    err;
  241.     
  242.     // Make each number is a long integer (in case it's a short integer) before extracting the data
  243.     err = AECoerceDesc(desc1, typeLongInteger, &longDesc);
  244.     if (err != noErr) goto done;
  245.     num1 = **(long **)longDesc.dataHandle;
  246.     (void) AEDisposeDesc(&longDesc);    // We're done with longDesc, so dispose of it
  247.     longDesc.dataHandle = NULL;            // Mark this as disposed
  248.     
  249.     err = AECoerceDesc(desc2, typeLongInteger, &longDesc);
  250.     if (err != noErr) goto done;
  251.     num2 = **(long **)longDesc.dataHandle;
  252.     // No need to dispose of this descriptor, as the code at "done" will do it for us
  253.     
  254.     switch (oper)
  255.     {
  256.         case kAEEquals:
  257.             *result = (num1 == num2);
  258.             break;
  259.         
  260.         case kAELessThan:
  261.             *result = (num1 < num2);
  262.             break;
  263.         
  264.         case kAELessThanEquals:
  265.             *result = (num1 <= num2);
  266.             break;
  267.         
  268.         case kAEGreaterThan:
  269.             *result = (num1 > num2);
  270.             break;
  271.         
  272.         case kAEGreaterThanEquals:
  273.             *result = (num1 >= num2);
  274.             break;
  275.         
  276.         default:
  277.             err = errAEBadTestKey;
  278.     }
  279.     
  280. done:
  281.     if (longDesc.dataHandle)
  282.         (void) AEDisposeDesc(&longDesc);
  283.  
  284.     return err;
  285. } // MyCompareInteger
  286.  
  287.  
  288. OSErr    MyCompareBoolean (DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  289. {
  290.     Boolean    bool1, bool2;
  291.     OSErr    err = noErr;
  292.     
  293.     // Apple events defines a boolean as a 1-byte value containing 1 for TRUE and 0 for FALSE
  294.     // We'll use a test to convert this into C's boolean notation, just to make this easier to
  295.     // debug
  296.     
  297.     bool1 = (**(char **)desc1->dataHandle) != 0;
  298.     bool2 = (**(char **)desc2->dataHandle) != 0;
  299.     
  300.     if (oper == kAEEquals) 
  301.         *result = (bool1 == bool2);
  302.     else
  303.         err = errAEBadTestKey;        // No other tests make sense
  304.  
  305.     return err;
  306. } // MyCompareBoolean
  307.